package com.gitee.fastmybatis.core.mapper;

import org.apache.ibatis.exceptions.TooManyResultsException;

import java.util.List;

/**
 * <pre>
 * {@link
 * @Test
 *     public void getOne() {
 *         TUser tUser = userMapper.query()
 *                 .gt(TUser::getId, 1)
 *                 .getOne()
 *                 // 如果有多条记录，抛出指定异常
 *                 .getIfThrow(new RuntimeException("查询失败"));
 *         System.out.println(tUser);
 *     }
 *     @Test
 *     public void getOne2() {
 *         TUser tUser = userMapper.query()
 *                 .gt(TUser::getId, 1)
 *                 // 追加limit 1
 *                 .getOne(true)
 *                 .get();
 *         System.out.println(tUser);
 *     }
 *
 *     @Test
 *     public void getOne3() {
 *         TUser tUser = userMapper.query()
 *                 .gt(TUser::getId, 1)
 *                 .getOne()
 *                 // 如果有多条数据，抛出TooManyResultsException异常
 *                 .getOrThrow();
 *         System.out.println(tUser);
 *     }
 *
 *     @Test
 *     public void getOne4() {
 *         OneResult<TUser> result = userMapper.query()
 *                 .eq(TUser::getId, 3)
 *                 .getOne();
 *         if (result.isError()) {
 *             throw new RuntimeException("");
 *         }
 *         Optional<TUser> optional = result.getOptional();
 *         if (optional.isPresent()) {
 *             System.out.println(optional.get());
 *         }
 *     }
 * </pre>
 * @author 六如
 */
public class OneResult<T> implements SearchResult<T> {

    private static final OneResult EMPTY = new OneResult<>(null, null);

    private final T data;

    private final TooManyResultsException exception;

    public static <E> OneResult<E> empty() {
        return EMPTY;
    }

    private OneResult(T data, TooManyResultsException exception) {
        this.data = data;
        this.exception = exception;
    }

    public static <V> OneResult<V> of(List<V> list, boolean appendLimitOne) {
        if (list == null || list.isEmpty()) {
            return OneResult.empty();
        }
        if (list.size() > 1 && !appendLimitOne) {
            return OneResult.of(new TooManyResultsException("Expected one result (or null) to be returned by getOne(), but found: " + list.size()));
        }
        return OneResult.of(list.get(0));
    }


    public static <V> OneResult<V> of(V data) {
        return new OneResult<>(data, null);
    }

    public static <V> OneResult<V> of(TooManyResultsException e) {
        return new OneResult<>(null, e);
    }

    /**
     * 返回结果
     *
     * @return 返回结果
     */
    @Override
    public T get() {
        return data;
    }

    @Override
    public RuntimeException getException() {
        return exception;
    }

    @Override
    public boolean isError() {
        return exception != null;
    }
}
